#include <cstdlib>
#include <iostream>
#include <string>
#include<vector>
#include <sys/types.h>
#include<wait.h>
#include <unistd.h>
#include<functional>
#include"Task.hpp"
#include"Channel.hpp"
// typedef std::function<void()> work_t
using work_t = std::function<void()>;

//错误码和状态
enum
{
    OK = 0,
    PipeError,
    ForkError,
    UsageError
};


class ProcessPool
{
  public:


    ProcessPool(int n,work_t w)
          :processnum(n)
          ,work(w)
    {}
    //初始化管道1，2，3
    // channels输出型参数
    // work回调

    //////////////////////////////////////////////////////////////////////////////////////////
    // 1.初始化
    int InitProcessPoll() 
    {
      //先创建指定个数个进程
      for (int i = 0; i < processnum; i++) 
      {
        //先有管道
        int pipefd[2] = {0};
        int n = pipe(pipefd);
        if (n < 0)
          return PipeError;

        //创建进程
        pid_t id = fork();
        if (id < 0)
          return ForkError;

        if (id == 0) {
          // child
          ::close(pipefd[1]); // read
          dup2(pipefd[0], 0);
          work();
          ::exit(0);
        }

        //父进程
        ::close(pipefd[0]); // read
        //代替下面写法
        channels.emplace_back(pipefd[1], id);
        // Channel ch(pipefd[1] , id);
        // channels.push_back(ch);
      }
      return OK;
    }
    ///////////////////////////////////////////////////////////////////////////////////////////////

    ///////////////////////////////////////////////////////////////////////////////////////////////
    // 2.派发任务
    void DispathTasks() 
    {
      int who = 0;
      int tasksnum = 20;
      // 2.派发任务
      while (tasksnum--) 
      {
        // a.选择一个任务
        int task = tm.SelectTask();

        // b.选择一个子进程管道
        //轮询选择
        Channel &curr = channels[who++];
        who %= channels.size();

        std::cout << "#################" << std::endl;
        std::cout << "send " << task << " to " << curr.Name()
                  << ",rest num:" << tasksnum << std::endl;
        std::cout << "#################" << std::endl;

        // c.派发任务
        curr.Send(task);

        sleep(1);
      }
    }

    //////////////////////////////////////////////////////////////////////////////////////////////
    // 3.退出
    void CleanProcessPoll() 
    {
      for (auto &c : channels) 
      {
        c.Close();
      }

      //等待子进程
      for (auto &c : channels) 
      {
        pid_t rid = waitpid(c.Id(), nullptr, 0);
        if (rid > 0)
          std::cout << "child" << getpid() << "wait...sucess" << std::endl;
      }
    }

    ////////////////////////////////////////////////////////////////////////////////////////////
    void DebugPrint() 
    {
      for (auto &c : channels) 
      {
        std::cout << c.Name() << std::endl;
      }
    }
    //////////////////////////////////////////////////////////////////////////////////////////////
  private:
    std::vector<Channel> channels;
    work_t work;
    int processnum;
};



